package com.ktwlsoft.archivemanage.domain.business.businessService.study;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ktwlsoft.archivemanage.config.FileStorageProperties;
import com.ktwlsoft.archivemanage.domain.business.businessService.FileService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.study.StudyCollectionRepositoryService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.study.StudyHistoryRepositoryService;
import com.ktwlsoft.archivemanage.domain.dao.entity.Account;
import com.ktwlsoft.archivemanage.domain.dao.entity.study.StudyClass;
import com.ktwlsoft.archivemanage.domain.dao.entity.study.StudyClassContent;
import com.ktwlsoft.archivemanage.domain.dao.entity.study.StudyClassGroup;
import com.ktwlsoft.archivemanage.domain.dao.repository.study.StudyClassContentMapper;
import com.ktwlsoft.archivemanage.domain.dao.repository.study.StudyClassGroupMapper;
import com.ktwlsoft.archivemanage.domain.dao.repository.study.StudyClassMapper;
import com.ktwlsoft.archivemanage.payload.Result;
import com.ktwlsoft.archivemanage.payload.TemFileResult;
import com.ktwlsoft.archivemanage.payload.exception.BusinessException;
import com.ktwlsoft.archivemanage.payload.study.studyClass.ClassContentPayload;
import com.ktwlsoft.archivemanage.payload.study.studyClass.ClassGroupPayload;
import com.ktwlsoft.archivemanage.payload.study.studyClass.SetInvalidRequest;
import com.ktwlsoft.archivemanage.payload.study.studyClass.StudyClassPagePayload;
import com.ktwlsoft.archivemanage.payload.study.studyClass.StudyClassPageRequest;
import com.ktwlsoft.archivemanage.payload.study.studyClass.StudyClassPayload;
import com.ktwlsoft.archivemanage.service.security.UserPrincipal;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
public class StudyClassService {

    private final StudyClassMapper studyClassMapper;

    private final StudyClassGroupMapper studyClassGroupMapper;

    private final StudyClassContentMapper studyClassContentMapper;

    private final StudyCollectionRepositoryService studyCollectionRepositoryService;

    private final FileStorageProperties fileStorageProperties;

    private final FileService fileService;

    private final StudyHistoryRepositoryService studyHistoryRepositoryService;

    public StudyClassService(StudyClassMapper studyClassMapper, StudyClassGroupMapper studyClassGroupMapper,
                             StudyClassContentMapper studyClassContentMapper, StudyCollectionRepositoryService studyCollectionRepositoryService, FileStorageProperties fileStorageProperties,
                             FileService fileService, StudyHistoryRepositoryService studyHistoryRepositoryService) {
        this.studyClassMapper = studyClassMapper;
        this.studyClassGroupMapper = studyClassGroupMapper;
        this.studyClassContentMapper = studyClassContentMapper;
        this.studyCollectionRepositoryService = studyCollectionRepositoryService;
        this.fileStorageProperties = fileStorageProperties;
        this.fileService = fileService;
        this.studyHistoryRepositoryService = studyHistoryRepositoryService;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveClass(StudyClassPayload request, StudyClass.ClassType classType) {
        StudyClass studyClass;
        if (request.getPurpose().equals("EDIT")) {
            // for update
            studyClass = studyClassMapper.selectByPrimaryKey(request.getId());
            studyClass.edit(request.getTitle(), request.getTag(), request.getMainImgUrl(), request.getClassifyId(),
                    request.getClassifyName(), request.getBannerShow(), request.getBannerImgUrl(), request.getState(),
                    classType);
            checkClass(request, studyClass, classType);
            studyClassMapper.updateByPrimaryKey(studyClass);
        } else if (request.getPurpose().equals("ADD")) {
            // for insert
            studyClass = new StudyClass(request.getTitle(), request.getTag(), request.getMainImgUrl(),
                    request.getClassifyId(), request.getClassifyName(), request.getBannerShow(),
                    request.getBannerImgUrl(), request.getState(), classType);

            checkClass(request, studyClass, classType);
            if (studyClassMapper.insert(studyClass) <= 0) {
                throw new BusinessException("新增课程失败!");
            }
        } else {
            throw new BusinessException("课程Purpose错误!");
        }
        saveClassGroup(request.getClassGroupPayloads(), studyClass);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    public void checkClass(StudyClassPayload request, StudyClass studyClass, StudyClass.ClassType classType) {
        // check if the setted state to UP, then set up datetime.
        if (request.getState().equals("UP")) {
            // check if the show banner classes count more than 6.
            if(request.getBannerShow()){
                if (studyClassMapper.checkBanners(true, classType.toString()) > 6) {
                    // throw business exception of shown banners is more than 6.
                    throw new BusinessException("显示的banner超过了6个");
                }
            }
            studyClass.setPublishAt(new Date());
            try {
                studyClass.setPublisherName(Objects.requireNonNull(UserPrincipal.getCurrentUser()).getRealName());
            } catch (NullPointerException nullException) {
                studyClass.setPublisherName("");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveClassGroup(List<ClassGroupPayload> classGroupPayloads, StudyClass studyClass) {
        for (ClassGroupPayload classGroupPayload : classGroupPayloads) {
            StudyClassGroup studyClassGroup;
            if (classGroupPayload.getPurpose().equals("ADD")) {
                studyClassGroup = new StudyClassGroup(classGroupPayload.getName(), studyClass.getId(),
                        studyClass.getTitle());
                if (studyClassGroupMapper.insert(studyClassGroup) <= 0) {
                    throw new BusinessException("插入课程组失败!");
                } else {
                    saveClassContent(classGroupPayload, studyClassGroup, studyClass);
                }
            } else if (classGroupPayload.getPurpose().equals("EDIT")) {
                if (classGroupPayload.getId() == null) {
                    throw new BusinessException("课程组Id不能为空!");
                }
                studyClassGroup = studyClassGroupMapper.selectByPrimaryKey(classGroupPayload.getId());
                if (studyClassGroup == null) {
                    throw new BusinessException("课程组在编辑时未找到!");
                }
                studyClassGroup.update(classGroupPayload.getName(), studyClass.getId(), studyClass.getTitle());
                studyClassGroupMapper.updateByPrimaryKey(studyClassGroup);
                saveClassContent(classGroupPayload, studyClassGroup, studyClass);
            } else if (classGroupPayload.getPurpose().equals("DELETE")) {
                studyClassGroup = new StudyClassGroup(classGroupPayload.getName(), studyClass.getId(),
                        studyClass.getTitle());
                studyClassGroup.setId(classGroupPayload.getId());
                studyClassGroupMapper.deleteByPrimaryKey(classGroupPayload.getId());
                saveClassContent(classGroupPayload, studyClassGroup, studyClass);
            } else {
                throw new BusinessException("课程组purpose设置错误!");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveClassContent(ClassGroupPayload classGroupPayload, StudyClassGroup studyClassGroup,
                                 StudyClass studyClass) {
        for (ClassContentPayload contentPayload : classGroupPayload.getClassContent()) {
            StudyClassContent classContent = null;
            if (contentPayload.getPurpose().equals("ADD")) {
                // ADD:
                try {
                    classContent = new StudyClassContent(studyClassGroup.getId(), studyClassGroup.getGroupName(),
                            studyClass.getId(), studyClass.getTitle(), contentPayload.getType(), contentPayload.getName(),
                            contentPayload.getVideoUrl(), contentPayload.getVideoDuration(), studyClass.getManagedState(),
                            studyClass.getState(),
                            contentPayload.getImgContent() != null ? contentPayload.getImgContent().getBytes("UTF-8") : null);
                }catch (Exception e){
                    e.printStackTrace();
                }
                if (studyClassContentMapper.insert(classContent) <= 0) {
                    throw new BusinessException("插入课程失败!");
                }
            } else if (contentPayload.getPurpose().equals("EDIT")) {
                // EDIT
                if (contentPayload.getId() == null) {
                    throw new BusinessException("课程内容ID不能为空!");
                }
                classContent = studyClassContentMapper.selectByPrimaryKey(contentPayload.getId());
                if (classContent == null) {
                    throw new BusinessException("未找到相应的课程内容!");
                }
                try {
                    classContent.update(studyClassGroup.getId(), studyClassGroup.getGroupName(), studyClass.getId(),
                            studyClass.getTitle(), contentPayload.getType(), contentPayload.getName(),
                            contentPayload.getVideoUrl(), contentPayload.getVideoDuration(), studyClass.getManagedState(),
                            studyClass.getState(),
                            contentPayload.getImgContent() != null ? contentPayload.getImgContent().getBytes("UTF-8") : null);
                }catch (Exception e){
                    e.printStackTrace();
                }
                studyClassContentMapper.updateByPrimaryKey(classContent);
            } else if (contentPayload.getPurpose().equals("DELETE")) {
                // DELETE
                if (contentPayload.getId() == null) {
                    throw new BusinessException("课程内容ID不能为空!");
                }
                studyClassContentMapper.deleteByPrimaryKey(contentPayload.getId());
            } else {
                throw new BusinessException("课程内容purpose设置错误!");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteClass(Long id) {
        studyClassMapper.deleteByPrimaryKey(id);
        studyClassGroupMapper.deleteByClassId(id);
        studyClassContentMapper.deleteByClassId(id);
        studyCollectionRepositoryService.getStudyCollectionMapper().deleteByClassId(id);
    }

    public PageInfo<StudyClassPagePayload> findList(StudyClassPageRequest request, StudyClass.ClassType classType) {
        PageHelper.startPage(request.getPn(), request.getPageSize());
        return new PageInfo<>(
                studyClassMapper.findPage(request.getState(), request.getClassifyId(), request.getPublishStart(),
                        request.getPublishEnd(), request.getKeywords(), request.getOrder(), classType));
    }

    @Transactional(rollbackFor = Exception.class)
    public int changeState(Long id, String state, Boolean bannerShow,String classType) {
        Account user = UserPrincipal.getCurrentUser();
        if (state.equals("UP")) {
            StudyClass studyClass = studyClassMapper.selectByPrimaryKey(id);
            if (studyClass.getManagedState().equals("INVALID")) {
                throw new BusinessException("违规内容不允许上架!");
            } else {
                if(bannerShow) {
                    List<StudyClass> studyClasses = studyClassMapper.selectByBannerShow(1, classType);
                    if (studyClasses.size() >= 6) {
                        throw new BusinessException("Banner显示超过6张!");
                    }
                }
                return studyClassMapper.changeState(id, state, bannerShow, user.getId(), user.getRealName(),"UP");
            }
        } else if (state.equals("DOWN")) {
            bannerShow = false;
            return studyClassMapper.changeState(id, state, bannerShow, user.getId(), user.getRealName(),"DOWN");
        } else {
            throw new BusinessException("state状态设置错误, 没有找到定义的类型:" + state);
        }
    }

    public Boolean isValid(Long id) {
        StudyClass studyClass = studyClassMapper.selectByPrimaryKey(id);
        return studyClass.getManagedState().equals("INVALID") ? false : true;
    }

    /**
     * 设置管理状态/违规处理
     *
     * @param request
     * @return
     */
    public Result<?> setManageState(SetInvalidRequest request) {
        // 获取需要违规处理的课程
        StudyClass studyClass = studyClassMapper.selectByPrimaryKey(request.getId());
        if (studyClass.equals(null)) {
            throw new BusinessException("该数据不存在!");
        }
        if (request.getIsInvalid()) {
            studyClass.setManagedState("INVALID");
            studyClass.setState("DOWN");
        } else {
            studyClass.setManagedState("NORMAL");
        }
        studyClass.setManageRemark(request.getManageRemark());
        try {
            studyClassMapper.updateByPrimaryKey(studyClass);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("更新出错");
        }
        return Result.ok(studyClass.getId());
    }

    public TemFileResult saveFile(MultipartFile file, String fileName, int sliceNum, Boolean isLast, String targetDir) {
        TemFileResult result = fileService.storeFileBySlice(file, fileName, sliceNum, isLast, targetDir);
        return result;
    }

    public String uploadImg(MultipartFile file, String classType) throws IOException {
        String targetLocation = "";
        if (classType.equals("MANAGE")) {
            targetLocation = fileStorageProperties.getManageClassDir();
        } else if (classType.equals("USER")) {
            targetLocation = fileStorageProperties.getUserClassDir();
        } else {
            throw new BusinessException("classType不正确: " + classType);
        }
        return fileService.storeFile(file, targetLocation);
    }
}
